import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { nanoid } from "nanoid";
import { ComponentPropsType } from "../../components/QuestionComponents";
import { getNextSelectedId, insertNewComponent } from "./utils";
import cloneDeep from "lodash.clonedeep";

export type ComponentInfoType = {
  fe_id: string; // todo
  type: string;
  title: string;
  isHidden?: boolean;
  isLocked?: boolean;
  props: ComponentPropsType;
};

export type ComponentsStateType = {
  selectedId: string;
  componentList: Array<ComponentInfoType>;
  copiedComponent: ComponentInfoType | null;
};

const INIT_STATE: ComponentsStateType = {
  selectedId: "",
  componentList: [],
  // 其他扩展
  copiedComponent: null,
};

export const componentsSlice = createSlice({
  name: "components",
  initialState: INIT_STATE,
  reducers: {
    // reset component
    resetComponents: (
      state: ComponentsStateType,
      action: PayloadAction<ComponentsStateType>
    ) => {
      return action.payload;
    },

    // updated selectedId
    // changeSelectedId: (state: ComponentsStateType, action: PayloadAction<string>) => {

    // }
    changeSelectedId: (
      state: ComponentsStateType,
      action: PayloadAction<string>
    ) => {
      state.selectedId = action.payload;
    },

    // add new component
    addComponent: (
      state: ComponentsStateType,
      action: PayloadAction<ComponentInfoType>
    ) => {
      const newComponent = action.payload;
      insertNewComponent(state, newComponent);
    },

    //update ComponentProps:
    changeComponentProps: (
      state: ComponentsStateType,
      action: PayloadAction<{ fe_id: string; newProps: ComponentPropsType }>
    ) => {
      const { fe_id, newProps } = action.payload;

      // 当前要修改的这个组件
      const curComp = state.componentList.find((c) => c.fe_id === fe_id);
      if (curComp) {
        curComp.props = {
          ...curComp.props,
          ...newProps,
        };
      }
    },

    // 删除选中的组件
    removeSelectedComponent: (state: ComponentsStateType) => {
      const { componentList = [], selectedId: removedId } = state;

      const newSelectedId = getNextSelectedId(removedId, componentList);
      state.selectedId = newSelectedId;

      // 当前要修改的这个组件
      const index = componentList.findIndex((c) => c.fe_id === removedId);
      componentList.splice(index, 1);
    },

    //隐藏、显示 组件
    changeComponentHidden: (
      state: ComponentsStateType,
      action: PayloadAction<{ fe_id: string; isHidden: boolean }>
    ) => {
      const { componentList = [] } = state;
      const { fe_id, isHidden } = action.payload;

      // 重新计算selectedId
      let newSelectedId = "";
      if (isHidden) {
        newSelectedId = getNextSelectedId(fe_id, componentList);
      } else {
        newSelectedId = fe_id;
      }
      state.selectedId = newSelectedId;

      const curComp = componentList.find((c) => c.fe_id === fe_id);
      if (curComp) {
        curComp.isHidden = isHidden;
      }
    },

    // lock/unlock 组件
    toggleComponentLocked: (
      state: ComponentsStateType,
      action: PayloadAction<{ fe_id: string }>
    ) => {
      const { fe_id } = action.payload;

      const curComp = state.componentList.find((c) => c.fe_id === fe_id);
      if (curComp) {
        curComp.isLocked = !curComp.isLocked;
      }
    },

    // copy cur component
    copySelectedComponent: (state: ComponentsStateType) => {
      const { selectedId, componentList = [] } = state;
      const SelectedComponent = componentList.find(
        (c) => c.fe_id === selectedId
      );
      if (SelectedComponent == null) return;
      state.copiedComponent = cloneDeep(SelectedComponent);
    },

    // paste
    pasteCopiedComponent: (state: ComponentsStateType) => {
      const { copiedComponent } = state;
      if (copiedComponent == null) return;

      //要把fe_id 给修改了，重要
      copiedComponent.fe_id = nanoid();
      insertNewComponent(state, copiedComponent);
      //插入 copiedComponent
    },

    selectPrevComponent: (state: ComponentsStateType) => {
      const { selectedId, componentList = [] } = state;
      const selectedIndex = componentList.findIndex(
        (c) => c.fe_id === selectedId
      );

      if (selectedIndex < 0) return;
      if (selectedIndex === 0) return;

      state.selectedId = componentList[selectedIndex - 1].fe_id;
    },

    selectNextComponent: (state: ComponentsStateType) => {
      const { selectedId, componentList = [] } = state;
      const selectedIndex = componentList.findIndex(
        (c) => c.fe_id === selectedId
      );

      if (selectedIndex < 0) return;
      if (selectedIndex === componentList.length -1 ) return;

      state.selectedId = componentList[selectedIndex + 1].fe_id;
    },
  },
});

export const {
  resetComponents,
  changeSelectedId,
  addComponent,
  changeComponentProps,
  removeSelectedComponent,
  changeComponentHidden,
  toggleComponentLocked,
  copySelectedComponent,
  pasteCopiedComponent,
  selectPrevComponent,
  selectNextComponent,
} = componentsSlice.actions;

export default componentsSlice.reducer;
